package cn.k23.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import javax.servlet.DispatcherType;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.EnumSet;
import java.util.List;

/**
 * @Description:
 * @Author: k23
 * @Date: 2022-03-19 14:50
 * @Version: 1.0
 */

@Configuration
@EnableWebMvc
//@EnableWebMvc ：开启Web MVC的配置支持。

@ComponentScan("cn.k23.controller")
@Import(value={ThymeleafConfig.class,MybatisConfig.class})
//实现WebApplicationInitializer接口
public class Webinit implements WebApplicationInitializer, WebMvcConfigurer {
    /*
    WebApplicationInitializer用于引导 Spring Web 应用

    WebMvcConfigurer配置类是Spring内部的一种配置方式，
    采用JavaBean的形式来代替传统的xml配置文件形式进行针对框架个性化定制
    可以自定义一些Handler，Interceptor，ViewResolver，MessageConverter
     */
    @Override
    public void onStartup(ServletContext c) throws ServletException {
        var ctx = new AnnotationConfigWebApplicationContext();
        ctx.register(this.getClass());
        ctx.setServletContext(c);

        //配置  DispatcherServlet servlet
        //DispatcherServlet是Spring MVC的前端控制器，
        ServletRegistration.Dynamic servlet = c.addServlet("dispatcher", new DispatcherServlet(ctx));
        servlet.addMapping("/");
        servlet.setLoadOnStartup(1);


        //为web项目添加一个编码过滤器
        var fc = new CharacterEncodingFilter("utf-8");
        fc.setEncoding("utf-8");
        fc.setForceRequestEncoding(true);
        fc.setForceResponseEncoding(true);
        var ff = c.addFilter("cc", fc);
        ff.setInitParameter("forceEncoding", "true"); //此主要解决PrintWriter out 输出编码方式
        //处理post表单，中文乱码
        ff.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD), true,"/*");

    }

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        //-------------配置当前springmvc 项目的消息转换器(防止乱码)
        var shmc = new StringHttpMessageConverter();
        shmc.setDefaultCharset(StandardCharsets.UTF_8);
        var list = List.of(MediaType.parseMediaType("text/html;charset=UTF-8"));
        shmc.setSupportedMediaTypes(list);
        converters.add(shmc);


        //解决json和java1.8 LocaleDate 日期格式乱码
        //需引入两个组件
        //如下配置需要引入jackson组件，主要解决json输出，面向接口开发用的
        var m2 = new MappingJackson2HttpMessageConverter();

        //设置日期格式  普通时间
        ObjectMapper objectMapper = new ObjectMapper();
        SimpleDateFormat smt = new SimpleDateFormat("yyyy-MM-dd"); //java.util.Date
        objectMapper.setDateFormat(smt);
        m2.setObjectMapper(objectMapper);


        //解决java8时间新特性 LocalDateTime 乱码问题
        var m = new JavaTimeModule();
        m.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        m.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        //LocalDate
        m.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        m.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        //LocalTime
        m.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern("HH:mm:ss")));
        m.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern("HH:mm:ss")));
        objectMapper.registerModule(m);
        m2.setObjectMapper(objectMapper);

        //设置中文编码格式
        m2.setSupportedMediaTypes(List.of(MediaType.parseMediaType("application/json;charset=UTF-8")));
        converters.add(m2);
    }


    //静态资源处理器
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        //addResourceHandler 虚拟路径   addResourceLocations真实的物理路径
        registry.addResourceHandler("/**").addResourceLocations("/static/");
        registry.addResourceHandler("/api/**").addResourceLocations("/api/");
        registry.addResourceHandler("/favicon.ico").addResourceLocations("/favicon.ico");
    }

    //处理上传文件
    @Bean
    public CommonsMultipartResolver multipartResolver() {
        CommonsMultipartResolver mu = new CommonsMultipartResolver();
        mu.setDefaultEncoding("utf-8");
        mu.setMaxUploadSize(1024 * 1024 * 100);
        return mu;
    }



}
